#!/bin/bash

# Test script for the bootstrap system
# This script tests the bootstrap functionality without actually connecting to remote hosts

set -e

# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color

# Function to print colored output
print_status() {
    echo -e "${BLUE}[TEST]${NC} $1"
}

print_success() {
    echo -e "${GREEN}[PASS]${NC} $1"
}

print_warning() {
    echo -e "${YELLOW}[WARN]${NC} $1"
}

print_error() {
    echo -e "${RED}[FAIL]${NC} $1"
}

# Test counter
TESTS_PASSED=0
TESTS_FAILED=0

# Function to run a test
run_test() {
    local test_name="$1"
    local test_command="$2"
    
    print_status "Running test: $test_name"
    
    if eval "$test_command"; then
        print_success "$test_name"
        ((TESTS_PASSED++))
    else
        print_error "$test_name"
        ((TESTS_FAILED++))
    fi
}

# Function to check if a file exists
check_file() {
    local file="$1"
    local description="$2"
    
    if [[ -f "$file" ]]; then
        print_success "$description exists: $file"
        return 0
    else
        print_error "$description missing: $file"
        return 1
    fi
}

# Function to check if a directory exists
check_directory() {
    local dir="$1"
    local description="$2"
    
    if [[ -d "$dir" ]]; then
        print_success "$description exists: $dir"
        return 0
    else
        print_error "$description missing: $dir"
        return 1
    fi
}

# Function to check file permissions
check_permissions() {
    local file="$1"
    local expected_perms="$2"
    local description="$3"
    
    local actual_perms=$(stat -c "%a" "$file" 2>/dev/null || stat -f "%Lp" "$file" 2>/dev/null)
    
    if [[ "$actual_perms" == "$expected_perms" ]]; then
        print_success "$description has correct permissions: $actual_perms"
        return 0
    else
        print_error "$description has wrong permissions: expected $expected_perms, got $actual_perms"
        return 1
    fi
}

# Function to check if a command exists
check_command() {
    local command="$1"
    local description="$2"
    
    if command -v "$command" >/dev/null 2>&1; then
        print_success "$description available: $command"
        return 0
    else
        print_error "$description missing: $command"
        return 1
    fi
}

# Function to test SSH key generation
test_ssh_key_generation() {
    local test_host="test.example.com"
    local test_key_name="test-key"
    local keys_dir="keys/$test_host"
    local key_path="$keys_dir/$test_key_name"
    
    # Clean up any existing test keys
    rm -rf "$keys_dir"
    
    # Create keys directory
    mkdir -p "$keys_dir"
    chmod 700 "$keys_dir"
    
    # Generate SSH key
    ssh-keygen -t ed25519 -f "$key_path" -N "" -C "test-bootstrap@$test_host" >/dev/null 2>&1
    
    # Check if files were created
    check_file "$key_path" "Private key"
    check_file "$key_path.pub" "Public key"
    
    # Check permissions
    check_permissions "$keys_dir" "700" "Keys directory"
    check_permissions "$key_path" "600" "Private key"
    check_permissions "$key_path.pub" "644" "Public key"
    
    # Check key format
    if grep -q "ssh-ed25519" "$key_path.pub"; then
        print_success "Public key has correct format"
    else
        print_error "Public key has wrong format"
        return 1
    fi
    
    # Clean up
    rm -rf "$keys_dir"
}

# Function to test sudoers configuration generation
test_sudoers_generation() {
    local test_user="testuser"
    local test_remote_dir="/opt/test"
    
    # Create test sudoers configuration
    local sudoers_config="# Gollect monitoring system sudoers configuration
# This file allows the $test_user user to run specific commands without password

# Allow systemctl commands for service management
$test_user ALL=(ALL) NOPASSWD: /bin/systemctl start gollect-trode-*
$test_user ALL=(ALL) NOPASSWD: /bin/systemctl stop gollect-trode-*
$test_user ALL=(ALL) NOPASSWD: /bin/systemctl restart gollect-trode-*
$test_user ALL=(ALL) NOPASSWD: /bin/systemctl status gollect-trode-*
$test_user ALL=(ALL) NOPASSWD: /bin/systemctl is-active gollect-trode-*
$test_user ALL=(ALL) NOPASSWD: /bin/systemctl enable gollect-trode-*
$test_user ALL=(ALL) NOPASSWD: /bin/systemctl disable gollect-trode-*
$test_user ALL=(ALL) NOPASSWD: /bin/systemctl daemon-reload

# Allow process management
$test_user ALL=(ALL) NOPASSWD: /bin/kill
$test_user ALL=(ALL) NOPASSWD: /bin/ps
$test_user ALL=(ALL) NOPASSWD: /usr/bin/pgrep

# Allow file operations in the trode directory
$test_user ALL=(ALL) NOPASSWD: /bin/chmod +x $test_remote_dir/*
$test_user ALL=(ALL) NOPASSWD: /bin/chown $test_user:$test_user $test_remote_dir/*
$test_user ALL=(ALL) NOPASSWD: /bin/mkdir -p $test_remote_dir
$test_user ALL=(ALL) NOPASSWD: /bin/rm -f $test_remote_dir/*.pid
$test_user ALL=(ALL) NOPASSWD: /bin/rm -f $test_remote_dir/*.log

# Allow network operations for monitoring
$test_user ALL=(ALL) NOPASSWD: /bin/netstat
$test_user ALL=(ALL) NOPASSWD: /bin/ss
$test_user ALL=(ALL) NOPASSWD: /usr/bin/lsof

# Allow system information gathering
$test_user ALL=(ALL) NOPASSWD: /bin/cat /proc/cpuinfo
$test_user ALL=(ALL) NOPASSWD: /bin/cat /proc/meminfo
$test_user ALL=(ALL) NOPASSWD: /bin/df
$test_user ALL=(ALL) NOPASSWD: /bin/free
$test_user ALL=(ALL) NOPASSWD: /usr/bin/top -b -n 1
$test_user ALL=(ALL) NOPASSWD: /usr/bin/uptime"
    
    # Write to temporary file
    local temp_file="/tmp/test-sudoers"
    echo "$sudoers_config" > "$temp_file"
    
    # Check if file was created
    check_file "$temp_file" "Sudoers configuration file"
    
    # Check sudoers syntax (if visudo is available)
    if command -v visudo >/dev/null 2>&1; then
        if visudo -c "$temp_file" >/dev/null 2>&1; then
            print_success "Sudoers configuration has valid syntax"
        else
            print_error "Sudoers configuration has invalid syntax"
            rm -f "$temp_file"
            return 1
        fi
    else
        print_warning "visudo not available, skipping syntax check"
    fi
    
    # Check that all required commands are included
    local required_commands=("systemctl" "kill" "ps" "pgrep" "chmod" "chown" "mkdir" "rm" "netstat" "ss" "lsof" "cat" "df" "free" "top" "uptime")
    
    for cmd in "${required_commands[@]}"; do
        if grep -q "$cmd" "$temp_file"; then
            print_success "Sudoers includes $cmd command"
        else
            print_error "Sudoers missing $cmd command"
            rm -f "$temp_file"
            return 1
        fi
    done
    
    # Clean up
    rm -f "$temp_file"
}

# Function to test bootstrap script syntax
test_bootstrap_script() {
    # Check if bootstrap script exists
    check_file "bootstrap_node.sh" "Bootstrap script"
    
    # Check if script is executable
    if [[ -x "bootstrap_node.sh" ]]; then
        print_success "Bootstrap script is executable"
    else
        print_error "Bootstrap script is not executable"
        return 1
    fi
    
    # Test script help
    if ./bootstrap_node.sh 2>&1 | grep -q "Usage:"; then
        print_success "Bootstrap script shows help when called without arguments"
    else
        print_error "Bootstrap script does not show help when called without arguments"
        return 1
    fi
}

# Function to test Go bootstrap module
test_go_bootstrap() {
    # Check if Go bootstrap file exists
    check_file "monitor/bootstrap.go" "Go bootstrap module"
    
    # Check if Go is available
    if command -v go >/dev/null 2>&1; then
        print_success "Go is available"
        
        # Try to build the monitor (this will check for syntax errors)
        if cd monitor && go build -o /tmp/test-monitor . >/dev/null 2>&1; then
            print_success "Monitor builds successfully with bootstrap module"
            rm -f /tmp/test-monitor
        else
            print_error "Monitor fails to build with bootstrap module"
            cd ..
            return 1
        fi
        cd ..
    else
        print_warning "Go not available, skipping build test"
    fi
}

# Function to test database schema
test_database_schema() {
    # Check if migration file exists
    check_file "migrate_to_trodes.sql" "Database migration file"
    
    # Check if migration includes bootstrap field
    if grep -q "bootstraped" "migrate_to_trodes.sql"; then
        print_success "Migration includes bootstraped field"
    else
        print_error "Migration missing bootstraped field"
        return 1
    fi
    
    # Check if migration includes bootstrap index
    if grep -q "idx_nodes_bootstraped" "migrate_to_trodes.sql"; then
        print_success "Migration includes bootstrap index"
    else
        print_error "Migration missing bootstrap index"
        return 1
    fi
}

# Function to test documentation
test_documentation() {
    # Check if documentation exists
    check_file "BOOTSTRAP_SYSTEM.md" "Bootstrap documentation"
    
    # Check for important sections
    local required_sections=("Overview" "Security Design" "Components" "Usage Examples" "Troubleshooting")
    
    for section in "${required_sections[@]}"; do
        if grep -q "^## $section" "BOOTSTRAP_SYSTEM.md"; then
            print_success "Documentation includes $section section"
        else
            print_error "Documentation missing $section section"
            return 1
        fi
    done
}

# Main test function
main() {
    echo "=========================================="
    echo "Bootstrap System Test Suite"
    echo "=========================================="
    echo ""
    
    # Test prerequisites
    print_status "Testing prerequisites..."
    run_test "Check ssh-keygen" "command -v ssh-keygen >/dev/null 2>&1"
    run_test "Check sshpass availability" "command -v sshpass >/dev/null 2>&1 || echo 'sshpass not available (will be installed during bootstrap)'"
    
    echo ""
    print_status "Testing components..."
    
    # Test bootstrap script
    run_test "Bootstrap script syntax and help" "test_bootstrap_script"
    
    # Test Go bootstrap module
    run_test "Go bootstrap module" "test_go_bootstrap"
    
    # Test database schema
    run_test "Database schema" "test_database_schema"
    
    # Test documentation
    run_test "Documentation" "test_documentation"
    
    echo ""
    print_status "Testing functionality..."
    
    # Test SSH key generation
    run_test "SSH key generation" "test_ssh_key_generation"
    
    # Test sudoers configuration
    run_test "Sudoers configuration generation" "test_sudoers_generation"
    
    echo ""
    echo "=========================================="
    echo "Test Results"
    echo "=========================================="
    echo "Tests passed: $TESTS_PASSED"
    echo "Tests failed: $TESTS_FAILED"
    echo "Total tests: $((TESTS_PASSED + TESTS_FAILED))"
    echo ""
    
    if [[ $TESTS_FAILED -eq 0 ]]; then
        print_success "All tests passed! Bootstrap system is ready."
        exit 0
    else
        print_error "Some tests failed. Please review the errors above."
        exit 1
    fi
}

# Run tests
main 